home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-01 / stevi69s.zip / CTAGS.C < prev    next >
Text File  |  1990-04-23  |  3KB  |  150 lines

  1. /*
  2.  * ctags - first cut at a UNIX ctags re-implementation
  3.  */
  4.  
  5. /*
  6.  * Caveats:
  7.  *
  8.  * Only simple function declarations are recognized, as in:
  9.  *
  10.  * type
  11.  * fname(...)
  12.  *
  13.  * where "fname" is the name of the function and must come at the beginning
  14.  * of a line. This is the form I always use, so the limitation doesn't
  15.  * bother me.
  16.  *
  17.  * Macros (with or without parameters) of the following form are also detected:
  18.  *
  19.  * "#" [white space] "define" [white space] NAME
  20.  *
  21.  * No sorting or detection of duplicate functions is done.
  22.  *
  23.  * If there are no arguments, a list of filenames to be searched is read
  24.  * from the standard input. Otherwise, all arguments are assumed to be
  25.  * file names.
  26.  *
  27.  * Tony Andrews
  28.  * August 1987
  29.  */
  30.  
  31. #include <stdio.h>
  32. #include <ctype.h>
  33. #include <string.h>
  34.  
  35. int    ac;
  36. char    **av;
  37.  
  38. #ifdef __TURBOC__        /* v1.1 some local prototypes */
  39. void dofile(char *fn, FILE *tp);        /* v1.1 */
  40. #endif
  41.  
  42. main(argc, argv)
  43. int    argc;
  44. char    *argv[];
  45. {
  46.     char    *fname, *nextfile();
  47.     FILE    *tp, *fopen();
  48.  
  49.     ac = argc;
  50.     av = argv;
  51.  
  52.     if ((tp = fopen("tags", "w")) == NULL) {
  53.         fprintf(stderr, "Can't create tags file\n");
  54.         exit(1);
  55.     }
  56.  
  57.     while ((fname = nextfile()) != NULL)
  58.         dofile(fname, tp);
  59.  
  60.     fclose(tp);
  61. /*    exit(0); */
  62.     return(0);    /* v1.1 */
  63. }
  64.  
  65. char *
  66. nextfile()    /* returns ptr to next file to be searched, null at end */
  67. {
  68.     static    char    buf[128];
  69.     static    int    ap = 1;
  70.     char    *gets();
  71.  
  72.     if (ac <= 1) {        /* read from stdin */
  73.         if (feof(stdin))
  74.             return (char *) NULL;
  75.         return (gets(buf));
  76.     } else {
  77.         if (ap < ac)
  78.             return av[ap++];
  79.         else
  80.             return (char *) NULL;
  81.     }
  82. }
  83.  
  84. #define    LSIZE    512    /* max. size of a line */
  85.  
  86. #define    BEGID(c)    (isalpha(c) || (c) == '_')
  87. #define    MIDID(c)    (isalpha(c) || isdigit(c) || (c) == '_')
  88.  
  89. void dofile(fn, tp)        /* v1.1 */
  90. char    *fn;
  91. FILE    *tp;
  92. {
  93.     FILE    *fp, *fopen();
  94.     char    *cp, *strchr();
  95.     char    lbuf[LSIZE];
  96.     char    func[LSIZE];
  97.     int    i, j;
  98.  
  99.     if ((fp = fopen(fn, "r")) == NULL) {
  100.         fprintf(stderr, "Can't open file '%s' - skipping\n", fn);
  101.         return;
  102.     }
  103.  
  104.     while (fgets(lbuf, LSIZE, fp) != NULL) {
  105.  
  106.         lbuf[strlen(lbuf)-1] = '\0';    /* bag the newline */
  107.  
  108.         if (BEGID(lbuf[0])) {        /* could be a function */
  109.             for (i=0; MIDID(lbuf[i]) ;i++)    /* grab the name */
  110.                 func[i] = lbuf[i];
  111.  
  112.             func[i] = '\0';        /* null terminate the name */
  113.  
  114.             /*
  115.              * We've skipped to the end of what may be a function
  116.              * name. Check to see if the next non-whitespace
  117.              * char is a paren,
  118.              * and make sure the closing paren is here too.
  119.              */
  120.             while (lbuf[i]==' ' || lbuf[i]=='\t') i++;
  121.             if (lbuf[i]=='(' && (((cp = strchr(lbuf,')'))!=NULL))) {
  122.                 *++cp = '\0';
  123.                 fprintf(tp, "%s\t%s\t/^%s$/\n", func,fn,lbuf);
  124.             }
  125.  
  126.         } else if (lbuf[0] == '#') {    /* could be a define */
  127.             for (i=1; isspace(lbuf[i]) ;i++)
  128.                 ;
  129.             if (strncmp(&lbuf[i], "define", 6) != 0)
  130.                 continue;
  131.  
  132.             i += 6;            /* skip "define" */
  133.  
  134.             for (; isspace(lbuf[i]) ;i++)
  135.                 ;
  136.  
  137.             if (!BEGID(lbuf[i]))
  138.                 continue;
  139.  
  140.             for (j=0; MIDID(lbuf[i]) ;i++, j++)
  141.                 func[j] = lbuf[i];
  142.  
  143.             func[j] = '\0';        /* null terminate the name */
  144.             lbuf[i] = '\0';
  145.             fprintf(tp, "%s\t%s\t/^%s/\n", func, fn, lbuf);
  146.         }
  147.     }
  148.     fclose(fp);
  149. }
  150.